package com.feiyun.erp.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import java.io.PrintWriter;

/**
 * SpringSecurity配置类
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    public static final String CONTENT_TYPE = "application/json;charset=utf-8";

    //加密器的创建方法
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PersistentTokenRepository repository;

    //配置账号信息
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        //在内存中保存账号和密码
//        auth.inMemoryAuthentication()
//                .withUser("zhangsan") //账号
//                .password(bCryptPasswordEncoder.encode("123456"))//密码必须加密
//                .roles("admin") //配置角色
//                .authorities("goods_list","goods_insert")//配置权限
//                .and()
//                .withUser("lisi") //账号
//                .password(bCryptPasswordEncoder.encode("123456"))//密码必须加密
//                .roles("user"); //配置角色
        //配置自定义的登录验证逻辑
        auth.userDetailsService(userDetailsService);
    }

    //配置网络请求的权限
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() //对请求进行权限配置
            .antMatchers("/login.html","/css/**","/js/**","/images/**").permitAll() //请求不需要登录验证
            .antMatchers("/index.html").hasAnyRole("管理员","销售主管","仓管主管","采购主管") //index.html需要admin角色
//             .antMatchers("/index.html").hasAuthority("goods_list") //需要goods_list权限
            .anyRequest().authenticated() //除了permitAll的请求外，其他请求都必须登录后访问
            .and()
                .formLogin() //开始配置登录
                .loginPage("/login.html") //配置登录的页面url
                .loginProcessingUrl("/doLogin") //配置处理登录请求的url，默认是login
//                .usernameParameter("username") //配置账号的参数名，
                .successHandler((req,resp,auth)->{
                    Object principal = auth.getPrincipal();
                    //将登录成功的用户信息返回给前端
                    resp.setContentType(CONTENT_TYPE);
                    PrintWriter writer = resp.getWriter();
                    writer.write(new ObjectMapper().writeValueAsString(principal)); //将Java对象转换为JSON字符串，发送
                    writer.close();
                }) //配置登录成功的处理器
                .failureHandler((req,resp,ex)->{
                  resp.setContentType(CONTENT_TYPE);
                    PrintWriter writer = resp.getWriter();
                    writer.write("账号或密码错误");
                    writer.close();
                }) //配置登录失败的处理器
            .and()
                .logout() // 配置登出（注销）
                .logoutUrl("/logout") //默认是logout
                .logoutSuccessHandler((req,resp,auth) -> {
                    resp.setContentType(CONTENT_TYPE);
                    PrintWriter writer = resp.getWriter();
                    writer.write("注销成功");
                    writer.close();
                })//注销成功的处理器
            .and()
                .exceptionHandling() //异常的处理
                .authenticationEntryPoint((req,resp,ex)->{
                    resp.setContentType(CONTENT_TYPE);
                    PrintWriter writer = resp.getWriter();
                    writer.write("请先进行登录");
                    writer.close();
                }) //没有进行登录验证的请求处理
            .and()
                .rememberMe() //配置记住我
                .rememberMeParameter("rememberMe") //记住我参数的名称，默认是rememberMe
                .tokenRepository(repository) //配置jdbc的实现
                .tokenValiditySeconds(60) //配置记住我的时间7 * 24 * 3600
            .and()
                .csrf().disable(); //禁用csrf攻击安全控制，否则表单会提交失败

        //配置http解决iframe不能跳转的问题
        http.headers().frameOptions().sameOrigin().httpStrictTransportSecurity().disable();
    }
}
